/**
******************************************************************************
  *
  * @file    Drivers/Src/motor-step.c
  * @author  hondent
  * @version V1.0.0
  * @date    2025-07-25
  *
  ******************************************************************************
  * @attention 步进电机(脉冲电动机) 驱动程序 TMC2209
  *  步进电机角度步距角：1.8° 电流 1.5A
  *  8细分控制精度=1.8°/8=0.225°，电机转一周需要1600个脉冲
  *  16细分控制精度=1.8°/16=0.1125° 电机转一周需要3200个脉冲
  *  32细分控制精度=1.8°/32=0.05625°，电机转一周需要6400个脉冲
  *  64细分控制精度=1.8°/64=0.0140625°，电机转一周需要12800个脉冲。
  *  EN：接GND, 电机才能工作。
  *  OA1\OA2\OB1\OB2: 接2项步进电机的A相±，B相±。  黑线A+ 绿线A- 红线B+ 蓝线B-
  *  VS（VM）：给电机的电压(4.75—>28VDC)。
  *  VCC_IO (VDD)：3.3V to 5V供电电压给TMC2209。
  *  CLK：连接时钟。
  *  STEP：脉冲输入。
  *  DIR：电机方向。
  *  DIAG：触发报警，当堵转后会发送一个脉冲给单片机，控制器收到后控制其停下。
  *  VCP/VREF：电流限制、电压比较器反馈或振荡器输出。
  *  INDEX：给出步进电机位置的信号。
  */
#include "motor-step.h"

#include "delay.h"
#include "stm32f4xx_gpio.h"

/**
 * Motor 引脚初始化
 */
void initMotor() {

    GPIO_InitTypeDef GPIO_InitStruct;

    //GPIO初始化
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIO_InitStruct.GPIO_Pin = ENABLE_PIN | DIRECTION_PIN | MS1_PIN | MS2_PIN | STEP_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 输出模式
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽模式，提高输出电流能力
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

    //初始化GPIO引脚
    GPIO_Init(GPIOD,&GPIO_InitStruct);
}

/**
 * 步进电机运行
 * @param direction 电机旋转方向 1——>正转 0——>反转
 * @param step  步数
 */
void motorRun(uint8_t direction,uint32_t step) {
    //开启电机运行
    setMotorEnable(1);

    //设置正转还是反转
    setMotorDirection(direction);

    uint32_t i;

    //发送脉冲信号
    for (i = 0; i < step; i++) {
        //发送低电平
        GPIO_WriteBit(STEP_GPIO,STEP_PIN,Bit_RESET);
        delayNop(1);
        GPIO_WriteBit(STEP_GPIO,STEP_PIN,Bit_SET);
        delayNop(1);
    }

    //关闭电机运行
    setMotorEnable(0);
}

/**
 * 设置电机生效
 * @param enable 0 关闭 1 开启
 */
void setMotorEnable(uint8_t enable) {
    delayMilliseconds(10);
    if (enable == 1) {
        GPIO_WriteBit(ENABLE_GPIO,ENABLE_PIN,Bit_SET);
    }else {
        GPIO_WriteBit(ENABLE_GPIO,ENABLE_PIN,Bit_RESET);
    }
}

/**
 * 步进电机停止
 */
void motorStop(void) {
    setMotorEnable(0);
}

/**
 * 设置电机正传反转 控制电机方向 引脚高电平——>正转 ;引脚低电平——>反转
 * @param direction 0 低电平 1高电平
 */
void setMotorDirection(uint8_t direction) {
    if (direction == 0) {
        GPIO_WriteBit(DIRECTION_GPIO,DIRECTION_PIN,Bit_RESET);
    } else {
        GPIO_WriteBit(DIRECTION_GPIO,DIRECTION_PIN,Bit_SET);
    }
}

/**
 * 设置电机微步分辨率
 * MS1_Pin 低电压 MS2_Pin 低电压 8细分控制精度=1.8°/8=0.225°，电机转一周需要1600个脉冲
 * MS1_Pin 高电压 MS2_Pin 高电压 16细分控制精度=1.8°/16=0.1125° 电机转一周需要3200个脉冲
 * MS1_Pin 高电压 MS2_Pin 低电压 32细分控制精度=1.8°/32=0.05625°，电机转一周需要6400个脉冲
 * MS1_Pin 低电压 MS2_Pin 高电压 64细分控制精度=1.8°/64=0.0140625°，电机转一周需要12800个脉冲。
 * @param pulse 微步分辨率 8 16 32 64
 */
void setMotorPulse(uint8_t pulse) {
    if (pulse == 16) {
        GPIO_WriteBit(MS1_GPIO,MS1_PIN,Bit_SET);
        GPIO_WriteBit(MS2_GPIO,MS2_PIN,Bit_SET);
    }else if (pulse == 32) {
        GPIO_WriteBit(MS1_GPIO,MS1_PIN,Bit_SET);
        GPIO_WriteBit(MS2_GPIO,MS2_PIN,Bit_RESET);
    }else if (pulse == 64) {
        GPIO_WriteBit(MS1_GPIO,MS1_PIN,Bit_RESET);
        GPIO_WriteBit(MS2_GPIO,MS2_PIN,Bit_SET);
    }else {
        GPIO_WriteBit(MS1_GPIO,MS1_PIN,Bit_RESET);
        GPIO_WriteBit(MS2_GPIO,MS2_PIN,Bit_RESET);
    }
}
